/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * ObjectDetailsPanel.java
 *
 * Created on Oct 6, 2010, 4:49:58 AM
 */

package com.celephais.objectGenerator;

import com.celephais.objectGenerator.FieldDetailPanel.FieldType;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.SwingUtilities;

/**
 *
 * @author Eugene Shen
 */
public class ObjectDetailsPanel extends javax.swing.JPanel {

	private static final long serialVersionUID = -3663767183348089078L;

	private ArrayList<FieldDetailPanel> fields;
	private ArrayList<Component> separators;

    /** Creates new form ObjectDetailsPanel */
    public ObjectDetailsPanel() {
		super();
		fields = new ArrayList<FieldDetailPanel>(20);
		separators = new ArrayList<Component>(20);
        initComponents();
		additionalInitComponents();
    }

	public List<FieldDetailPanel> getFields() {
		return fields;
	}

	public void removeField(FieldDetailPanel fdp) {
		int idx = fdp.getIndex();
		contentBox.remove(fields.remove(idx));
		contentBox.remove(separators.remove(idx));
		for (int i=idx; i<fields.size(); ++i) {
			fields.get(i).setIndex(i);
		}
		revalidate();
		repaint();
	}

	public boolean validateFieldNames() {
		StringBuilder errorMsg = new StringBuilder();
		HashSet<String> names = new HashSet<String>();
		int errorCount = 0;
		for (FieldDetailPanel fdp : fields) {
			String name = fdp.getFieldName();
			if (names.contains(name)) {
				errorMsg.append("Field ").append(fdp.getIndex()+1).append(": ")
						.append("The field name ").append(name)
						.append(" has been declared more than once.\r\n");
				++errorCount;
			}
			else if (name.length() < 1) {
				errorMsg.append("Field ").append(fdp.getIndex()+1).append(": ")
						.append("Field names cannot be empty.\r\n");
				++errorCount;
			}
			else {
				char first = name.charAt(0);
				if (first != '_' && !Character.isLetter(first)) {
					errorMsg.append("Field ").append(fdp.getIndex()+1).append(": ")
							.append("Field names must begin with either a letter or _ (underscore).\r\n");
					++errorCount;
				}
				else {
					boolean okay = true;
					for (int i=1; i<name.length(); ++i) {
						first = name.charAt(i);
						if (first != '_' && !Character.isLetterOrDigit(first)) {
							errorMsg.append("Field ").append(fdp.getIndex()+1).append(": ")
									.append("Field names must only contain letters, digits, or _ (underscore).  ")
									.append(first).append(" is not a valid character for field names.\r\n");
							++errorCount;
							okay = false;
							break;
						}
					}
					if (okay) {
						names.add(name);
					}
				}
			}
		}

		if (errorCount == 0) {
			return true;
		}
		else {
			errorMsg.append("\r\n").append(errorCount).append(" field name errors detected.");
			JOptionPane.showMessageDialog(this, errorMsg.toString(), "Field Name Errors", JOptionPane.ERROR_MESSAGE);
			return false;
		}
	}

	public boolean hasTextField() {
		for (FieldDetailPanel fdp : fields) {
			if (fdp.getType() == FieldType.TEXT) {
				return true;
			}
		}
		return false;
	}

	public boolean hasReferenceField() {
		for (FieldDetailPanel fdp : fields) {
			if (fdp.getType() == FieldType.REF) {
				return true;
			}
		}
		return false;
	}

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        scrollPane = new JScrollPane();
        objectFieldsLabel = new JLabel();
        addFieldBtn = new JButton();

        setName("Form"); // NOI18N

        scrollPane.setName("scrollPane"); // NOI18N

        objectFieldsLabel.setText("Object Fields");
        objectFieldsLabel.setName("objectFieldsLabel"); // NOI18N

        addFieldBtn.setText("Add Field");
        addFieldBtn.setToolTipText("Add a new field to this object");
        addFieldBtn.setName("addFieldBtn"); // NOI18N

        GroupLayout layout = new GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(Alignment.LEADING)
                    .addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, 376, Short.MAX_VALUE)
                    .addComponent(objectFieldsLabel)
                    .addComponent(addFieldBtn))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(objectFieldsLabel)
                .addPreferredGap(ComponentPlacement.UNRELATED)
                .addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, 207, Short.MAX_VALUE)
                .addPreferredGap(ComponentPlacement.UNRELATED)
                .addComponent(addFieldBtn)
                .addContainerGap())
        );
    }// </editor-fold>//GEN-END:initComponents

	private void additionalInitComponents() {
		contentBox = new Box(BoxLayout.Y_AXIS);
		scrollPane.setViewportView(contentBox);

		addFieldBtn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				final FieldDetailPanel fdp = new FieldDetailPanel(ObjectDetailsPanel.this, fields.size());
				Component strut = Box.createVerticalStrut(1);
				fields.add(fdp);
				separators.add(strut);
				contentBox.add(fdp);
				contentBox.add(strut);
				fdp.requestFocus();
				ObjectDetailsPanel.this.revalidate();
				SwingUtilities.invokeLater(new Runnable() {
					public void run() {
						scrollPane.getVerticalScrollBar().setValue(contentBox.getHeight());
					}
				});
			}
		});

//		for (int i=0; i<100; ++i) {
//			contentBox.add(new JLabel("Item " + i));
//		}
	}

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private JButton addFieldBtn;
    private JLabel objectFieldsLabel;
    private JScrollPane scrollPane;
    // End of variables declaration//GEN-END:variables

	private Box contentBox;
}
